﻿using System;
using System.Linq;
using System.Collections.Generic;
using System.Xml.Linq;
using System.Net;
using System.Windows;
using SilverQuery;
using SilverPortal;

namespace SilverPortal.Modules
{
	public class DiggModule : SilverPortalModule
	{
		private string _appKey;
		private string _storyTemplate;
		private List<DiggContainer> _containers;

		public DiggModule()
		{
		}

		protected override void Load()
		{
			base.Log.Info("Digg module begin loading");
			base.RegisterCssResource("SilverPortal.Modules.DiggModule.css");

			base.Container.addClass("digg");
			var template = @q(TemplateHtml);
			var ul = @q("ul", template);
			_storyTemplate = ul.html();
			ul.empty();

			@q("<img />").attr("src", "http://digg.com/img/badges/16x16-digg-guy.png").appendTo(base.GetHeaderRightContent());

			template.appendTo(base.Container);

			//string appKey = null;
			if (!base.Config.Settings.TryGetValue("appkey", out _appKey))
				_appKey = SilverPortalComponent.CurrentUriPath();

			// Make a call to the List Topics API call.
			base.Log.Info("Begin fetching Digg topics");
			Ajax.get("http://services.digg.com/topics", new map() { { "appkey", _appKey } }, (data, error) =>
			{
				if (error != null)
				{
					base.Log.Info("Error loading Digg topics");
					base.DisplayError("Could not load topics", error);
					return;
				}
				else
				{
					base.Log.Info("Digg topics done loading.");
					XDocument xml = XDocument.Parse(data);
					InitTopics(template, xml);
				}

				base.DoneLoading();
			});
		}

		private void InitTopics(jQuery template, XDocument xml)
		{
			string selectedTopic = base.State["diggTopic"];
			_containers = new List<DiggContainer>();

			foreach (XElement t in xml.Descendants("topic"))
			{
				var celem = t.Element("container");
				DiggContainer container = _containers.FirstOrDefault(c => c.ShortName == celem.Attribute("short_name").Value);
				if (container == null)
					_containers.Add(container = new DiggContainer()
					{
						ShortName = celem.Attribute("short_name").Value,
						Name = celem.Attribute("name").Value,
						Topics = new List<DiggTopic>()
					});

				container.Topics.Add(new DiggTopic()
				{
					Name = t.Attribute("name").Value,
					ShortName = t.Attribute("short_name").Value
				});
			}

			var select = @q("select", template);
			foreach (DiggContainer c in _containers)
			{
				AppendOption(select, c, false, selectedTopic == c.ShortName);
				foreach (DiggTopic t in c.Topics)
					AppendOption(select, t, true, selectedTopic == t.ShortName);
			}

			select.change(OnTopicSelected);

			// If there is a 
			if (selectedTopic != null)
			{
				LoadStories(selectedTopic,
					_containers.Any(c => c.ShortName == selectedTopic),
					() => base.DoneLoading());
			}
		}

		private bool OnTopicSelected(Event e)
		{
			var select = @q(e.target);
			var selectedValue = select.children("option:selected").val();
			if (selectedValue != "0")
			{
				base.State["diggTopic"] = selectedValue;
				bool isContainer = _containers.Any(c => c.ShortName == selectedValue);
				LoadStories(selectedValue, isContainer, null);
			}

			return false;
		}

		private void LoadStories(string topic, bool isContainer, Callback cb)
		{
			var url = String.Concat("http://services.digg.com/stories/",
				(isContainer ? "container/" : "topic/"), topic, "/popular");

			Ajax.get(url, new map() { { "count", "15" }, { "appkey", _appKey } }, (data, error) =>
			{
				if (error != null)
					base.DisplayError("Could not load stories.", error);
				else
				{
					base.Log.Info("Digg stories loaded.");
					BindStories(XDocument.Parse(data));
					if (cb != null)
						cb();
				}
			});
		}

		private void AppendOption(jQuery select, DiggTopic t, bool indent, bool selected)
		{
			var opt = @q("<option/>").attr("value", t.ShortName);
			opt.html((indent ? "&nbsp;&nbsp;&nbsp;" : string.Empty) + t.Name);
			if (selected)
				opt.attr("selected", "selected");
			opt.appendTo(select);
		}

		private void BindStories(XDocument xml)
		{
			try
			{
				var ul = @q("div.results ul", this.Container);
				ul.empty();

				foreach (XElement story in xml.Descendants("story"))
				{
					var item = @q(_storyTemplate);
					@q("h4 a", item).html(story.Element("title").Value).attr("href", story.Attribute("link").Value);

					var thumb = story.Element("thumbnail");
					if (thumb == null)
						@q("img.thumb", item).remove();
					else
						@q("img.thumb", item).attr("src", thumb.Attribute("src").Value)
							.attr("width", thumb.Attribute("width").Value)
							.attr("height", thumb.Attribute("height").Value);

					@q("p.description", item).html(story.Element("description").Value);
					var links = @q("ul.links", item);

					@q("<li />").addClass("diggs").append(@q("<a/>")
						.attr("target", "_blank")
						.attr("href", story.Attribute("href").Value)
						.html(story.Attribute("diggs").Value + " diggs"))
					.appendTo(links);

					@q("<li />").addClass("comments").append(@q("<a/>")
						.attr("target", "_blank")
						.attr("href", story.Attribute("href").Value)
						.html(story.Attribute("comments").Value + " comments"))
					.appendTo(links);

					ul.append(item);
				}
			}
			catch (Exception e)
			{
				base.DisplayError("Error binding stories", e);
			}
		}

		private class DiggTopic
		{
			public string Name { get; set; }
			public string ShortName { get; set; }
		}

		private class DiggContainer : DiggTopic
		{
			public List<DiggTopic> Topics { get; set; }
		}

		private const string TemplateHtml = @"
<div class=""header"">
	<span>Topic:</span><select><option value=""0"">==Select Topic==</option></select>
</div>
<div class=""results"">
<ul>
	<li>
		<h4><a target=""_blank""></a></h4>
		<img class=""thumb"" />
		<p class=""description""></p>
		<ul class=""links""></ul>
</li>
</ul>
</div>";
	}
}
